﻿using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MugenInjection.Core.Components;
using MugenInjection.Interface.Components;
using Should;

namespace MugenInjectionTest.Components
{
    public interface IFakeBehavior
    {
    }

    public class FakeBehavior : IFakeBehavior
    {
    }

    [TestClass]
    public class BehaviorManagerComponentTest : ComponentTestBase<IBehaviorManagerComponent>
    {
        [TestMethod]
        public void MainOperationsTest()
        {
            using (var injector = GetInjector())
            {
                IBehaviorManagerComponent behaviorManagerComponent = ConfigureComponent(injector);

                behaviorManagerComponent.IsExist<IFakeBehavior>().ShouldBeFalse();
                IFakeBehavior fakeBehavior;
                behaviorManagerComponent.TryGet(out fakeBehavior).ShouldBeFalse();
                fakeBehavior.ShouldBeNull();
                behaviorManagerComponent.Add<IFakeBehavior, FakeBehavior>();
                behaviorManagerComponent.IsExist<IFakeBehavior>().ShouldBeTrue();

                //Geting a type behavior.
                fakeBehavior = behaviorManagerComponent.Get<IFakeBehavior>();
                fakeBehavior.ShouldNotBeNull();

                behaviorManagerComponent.TryGet(out fakeBehavior).ShouldBeTrue();
                fakeBehavior.ShouldNotBeNull();

                //Geting all behaviors.
                IList<IFakeBehavior> fakeBehaviors = behaviorManagerComponent.GetAll<IFakeBehavior>();
                fakeBehaviors.Count.ShouldEqual(1);
                fakeBehaviors[0].ShouldBeType<FakeBehavior>();

                //Adding a constant behavior.
                var behavior = new FakeBehavior();
                behaviorManagerComponent.Add<IFakeBehavior>(behavior);

                //Checking constant and type behaviors.
                behaviorManagerComponent.IsExist<IFakeBehavior>().ShouldBeTrue();
                fakeBehaviors = behaviorManagerComponent.GetAll<IFakeBehavior>();
                fakeBehaviors.Count.ShouldEqual(2);
                fakeBehaviors[0].ShouldBeType<FakeBehavior>();
                fakeBehaviors[1].ShouldEqual(behavior);

                //Removing all behvaiors and checking.
                behaviorManagerComponent.Remove<IFakeBehavior>();
                behaviorManagerComponent.IsExist<IFakeBehavior>().ShouldBeFalse();
            }
        }

        [TestMethod]
        public void NotFoundBehaviorTest()
        {
            using (var injector = GetInjector())
            {
                IBehaviorManagerComponent behaviorManagerComponent = ConfigureComponent(injector);
                Action action = () => behaviorManagerComponent.Get<IFakeBehavior>();
                action.ShouldThrow<KeyNotFoundException>();
            }
        }

        [TestMethod]
        public void CloneBehaviorsTest()
        {
            using (var injector = GetInjector())
            {
                IBehaviorManagerComponent behaviorManagerComponent = ConfigureComponent(injector);

                var fakeBehavior = new FakeBehavior();
                behaviorManagerComponent.Add<IFakeBehavior, FakeBehavior>();
                behaviorManagerComponent.Add<IFakeBehavior>(fakeBehavior);

                behaviorManagerComponent.CopyBehavior = false;
                var component = (IBehaviorManagerComponent)behaviorManagerComponent.Clone();
                using (var newInjector = GetInjector())
                {
                    newInjector.Components.RemoveAll<IBehaviorManagerComponent>();
                    newInjector.Components.Add(component);
                    component.IsExist<IFakeBehavior>().ShouldBeFalse();
                }

                behaviorManagerComponent.CopyBehavior = true;
                component = (IBehaviorManagerComponent)behaviorManagerComponent.Clone();
                behaviorManagerComponent.Remove<IFakeBehavior>();
                using (var newInjector = GetInjector())
                {
                    newInjector.Components.RemoveAll<IBehaviorManagerComponent>();
                    newInjector.Components.Add(component);

                    component.IsExist<IFakeBehavior>().ShouldBeTrue();
                    var fakeBehaviors = component.GetAll<IFakeBehavior>();
                    fakeBehaviors.Count.ShouldEqual(2);
                    fakeBehaviors[0].ShouldBeType<FakeBehavior>();
                    fakeBehaviors[1].ShouldEqual(fakeBehavior);
                }
            }
        }

        #region Overrides of ComponentTestBase<IBehaviorManagerComponent>

        protected override IBehaviorManagerComponent CreateNew()
        {
            return new BehaviorManagerComponent();
        }

        #endregion
    }
}